using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Text.RegularExpressions;

namespace Cartoon
{
    class HtmlAnalyze
    { 
        public bool Activate(out  ICollection<Episode> episodes, out ICollection<Episode>  autoDowns)
        {
            try
            {
                episodes = Episodes(Global.NewCartoonUrl);
                autoDowns = new List<Episode>();
                foreach (Episode episode in episodes)
                {
                    bool aleadyDown = false;

                    foreach (string name in Config.Instance.FavoriteList)
                    {
                        aleadyDown = episode.Name.Contains(name);
                        if (aleadyDown)
                        {
                            episode.Favorited = true;
                            break;
                        }
                    }

                    if (!aleadyDown)
                        continue;

                    if (!Config.Instance.DownHistoryList.Contains(episode.Name))           
                        autoDowns.Add(episode);
                }
                return true;
            }
            catch
            {
                episodes = null;
                autoDowns = null;
                return false;
            }
        }


        public static ICollection<Episode> Episodes(string episodesUrl)
        {
            if (episodesUrl == null)
                throw new ArgumentNullException("episodesUrl");

            WebClient client = new WebClient();
            client.Encoding = Encoding.GetEncoding("GB2312");

            string html = client.DownloadString(episodesUrl);

            List<Part> parts = Parse.ParseAll(html);

            Regex regex = new Regex(@"\bctdown/\d+.htm\b");

            List<Episode> episodes = new List<Episode>();
            for (int i = 0; i < parts.Count; ++i)
            {
                Part part = parts[i];
                if (part.Type != PartType.Tag)
                    continue;

                Tag tag = part as Tag;
                if (tag.End)
                    continue;

                if (string.Compare(tag.Name, "A", true) != 0)
                    continue;

                HtmlAttribute attribute = tag.AttrList.Find("href");
                if (attribute == null)
                    continue;

                string url = attribute.Value;
                if (!regex.IsMatch(url))
                    continue;

                ++i;
                part = parts[i];
                if (part.Type != PartType.Text)
                    continue;

                Text text = part as Text;
                string name = text.Value;

                episodes.Add(new Episode(name, url));
            }
            return episodes;
        }

        public static ICollection<Episode> GetComic(string episodesUrl)
        {
            if (episodesUrl == null)
                throw new ArgumentNullException("episodesUrl");

            WebClient client = new WebClient();
            client.Encoding = Encoding.GetEncoding("GB2312");

            Uri baseUri = new  Uri(episodesUrl);

            string html = client.DownloadString(baseUri);

            List<Part> parts = Parse.ParseAll(html);

            List<Episode> episodes = new List<Episode>();
            for (int i = 0; i < parts.Count; ++i)
            {
                Part part = parts[i];
                if (part.Type != PartType.Tag)
                    continue;

                Tag tag = part as Tag;
                if (tag.End)
                    continue;

                if (string.Compare(tag.Name, "A", true) != 0)
                    continue;

                HtmlAttribute attribute = tag.AttrList.Find("href");
                if (attribute == null)
                    continue;

                string url = attribute.Value;
                if (!url.Contains("Browser.html?c="))
                    continue;

                ++i;
                part = parts[i];
                if (part.Type != PartType.Text)
                    continue;

                Text text = part as Text;
                string name = text.Value;

                Uri urlTo = new Uri(baseUri, url);

                episodes.Add(new Episode(name, urlTo.ToString()));
            }
            return episodes;
        }

        public static string EpisodeFileUrl(string baseUrl, string episodeUrl)
        {
            if (episodeUrl == null)
                throw new ArgumentNullException("episodeUrl");

            WebClient client = new WebClient();
            client.Encoding = Encoding.GetEncoding("GB2312");
            //string searchString = "var thunder_url = \"";
            string searchString = "thunder://";        
       
            Uri urlTo = new Uri(new Uri(baseUrl), episodeUrl);

            string html = client.DownloadString(urlTo);
            int searchIndex= html.IndexOf(searchString, StringComparison.OrdinalIgnoreCase);
            if (searchIndex == -1)
                throw new Exception("Can not find cartoon download url!");

            searchIndex += searchString.Length;
            int endSearch = html.IndexOf('"', searchIndex);
            string url = html.Substring(searchIndex, endSearch - searchIndex);
            return Decode64(url);
        }

        static string Decode64(string input)
        {
            List<byte> output = new List<byte>();
            if (input == null)
                throw new ArgumentNullException("input");

            if (input.Length % 4 != 0)
                throw new ArgumentException("input length error");

            Regex regex = new Regex("[^A-Za-z0-9+/=]");
            if (regex.IsMatch(input))
                throw new ArgumentException("input contains an invalid character");

            string keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
            int i = 0;
            do
            {
                int enc1 = keyStr.IndexOf(input[i++]);
                int enc2 = keyStr.IndexOf(input[i++]);
                int enc3 = keyStr.IndexOf(input[i++]);
                int enc4 = keyStr.IndexOf(input[i++]);

                byte chr1 = (byte)((enc1 << 2) | (enc2 >> 4));
                byte chr2 = (byte)(((enc2 & 15) << 4) | (enc3 >> 2));
                byte chr3 = (byte)(((enc3 & 3) << 6) | enc4);

                output.Add(chr1);

                if (enc3 != 64)
                    output.Add(chr2);

                if (enc4 != 64)
                    output.Add(chr3);

            } while (i < input.Length);


            string url = Encoding.GetEncoding("GB18030").GetString(output.ToArray());
            regex = new Regex("^AA|ZZ$");
            return regex.Replace(url, "");
        }
    }
}
